Ammo().then(function(Ammo) {


//  初始化着色器程序，让 WebGL 知道如何绘制我们的数据
function initShaderProgram(gl, vsSource, fsSource) {
  const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vsSource);
  const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fsSource);

  // 创建着色器程序

  const shaderProgram = gl.createProgram();
  gl.attachShader(shaderProgram, vertexShader);
  gl.attachShader(shaderProgram, fragmentShader);
  gl.linkProgram(shaderProgram);

  // 如果创建失败，alert
  if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
    alert(
      "Unable to initialize the shader program: " +
        gl.getProgramInfoLog(shaderProgram),
    );
    return null;
  }

  return shaderProgram;
}

//
// 创建指定类型的着色器，上传 source 源码并编译
//
function loadShader(gl, type, source) {
  const shader = gl.createShader(type);

  // Send the source to the shader object

  gl.shaderSource(shader, source);

  // Compile the shader program

  gl.compileShader(shader);

  // See if it compiled successfully

  if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
    alert(
      "An error occurred compiling the shaders: " + gl.getShaderInfoLog(shader),
    );
    gl.deleteShader(shader);
    return null;
  }

  return shader;
}


//
// Initialize a texture and load an image.
// When the image finished loading copy it into the texture.
//
function loadTexture(gl, url) {
  const texture = gl.createTexture();
  gl.bindTexture(gl.TEXTURE_2D, texture);

  // Because images have to be downloaded over the internet
  // they might take a moment until they are ready.
  // Until then put a single pixel in the texture so we can
  // use it immediately. When the image has finished downloading
  // we'll update the texture with the contents of the image.
  const level = 0;
  const internalFormat = gl.RGBA;
  const width = 1;
  const height = 1;
  const border = 0;
  const srcFormat = gl.RGBA;
  const srcType = gl.UNSIGNED_BYTE;
  const pixel = new Uint8Array([0, 255, 255, 255]); // opaque blue
  gl.texImage2D(
    gl.TEXTURE_2D,
    level,
    internalFormat,
    width,
    height,
    border,
    srcFormat,
    srcType,
    pixel,
  );

  const image = new Image();
	
  //image.crossOrigin = "anonymous";//test
  image.onload = function() {

    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.texImage2D(
      gl.TEXTURE_2D,
      level,
      internalFormat,
      srcFormat,
      srcType,
      image,
    );

    // WebGL1 has different requirements for power of 2 images
    // vs. non power of 2 images so check if the image is a
    // power of 2 in both dimensions.

      // No, it's not a power of 2. Turn off mips and set
      // wrapping to clamp to edge
	  /*
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);*/
	  
	  


  };
  
	image.src = url;
	console.log("preparing");
  // gl.NEAREST is also allowed, instead of gl.LINEAR, as neither mipmap.
	gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
	// Prevents s-coordinate wrapping (repeating).
	gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
	// Prevents t-coordinate wrapping (repeating).
	gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);

  return texture;
}






function main() {
	const canvas = document.querySelector("#glcanvas");

	const gl = canvas.getContext("webgl2");


	if (!gl) {
		alert("无法初始化 WebGL2，你的浏览器、操作系统或硬件等可能不支持 WebGL2。");
		return;
	}

	gl.viewport(0, 0, screen_width, screen_height);
	
	gl.clearColor(0.0, 0.0, 0.0, 1.0);

	gl.clear(gl.COLOR_BUFFER_BIT);
  //启用混合
	//gl.enable(gl.BLEND);
	//gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
	gl.enable(gl.DEPTH_TEST); // Enable depth testing
	gl.depthFunc(gl.LEQUAL); // Near things obscure far things
	
	//const default_framebuffer = gl.getParameter(gl.FRAMEBUFFER_BINDING);
	
	//使用拓展 帧缓冲数据类型支持
	//const ext = gl.getExtension("EXT_color_buffer_float");
  
	//用于HDR的帧缓冲
	//let FBO_hdr = gl.createFramebuffer();
	//let tex_hdr = gl.createTexture();
	//纹理
	//gl.bindTexture(gl.TEXTURE_2D, tex_hdr);
	//gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA16F, screen_width, screen_height, 0, gl.RGBA, gl.FLOAT, null);//*********************
	//gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
	//gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
	//深度缓冲
	//let dep_hdr = gl.createRenderbuffer();
	//gl.bindRenderbuffer(gl.RENDERBUFFER, dep_hdr);
	//gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, screen_width, screen_height);
	
	//gl.bindFramebuffer(gl.FRAMEBUFFER, FBO_hdr);
	/*
	gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex_hdr, 0);
	gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, dep_hdr);
	if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) !== gl.FRAMEBUFFER_COMPLETE){
		alert("Framebuffer not complete!");
	}
	gl.bindFramebuffer(gl.FRAMEBUFFER, default_framebuffer);*/
	
  
  
	
	
	
	
	//编译链接着色器
	const shaderProgram_cube = initShaderProgram(gl, vertex_cube_source, fragment_cube_source);
	const shaderProgram_ground = initShaderProgram(gl, vertex_ground_source, fragment_ground_source);

	//顶点属性
	const programInfo_cube = {
		program: shaderProgram_cube,
		attribLocations: {
			vertexPosition: gl.getAttribLocation(shaderProgram_cube, "aPos"),
			normPosition: gl.getAttribLocation(shaderProgram_cube, "norm"),
			coordPosition: gl.getAttribLocation(shaderProgram_cube, "coord"),//纹理坐标
		},
		uniformLocations: {
			projectionMatrix: gl.getUniformLocation(shaderProgram_cube, "pers"),
			rotateMatrix: gl.getUniformLocation(shaderProgram_cube, "rota"),
			partrotateMatrix: gl.getUniformLocation(shaderProgram_cube, "partrota"),//局部坐标旋转与平移矩阵
			moveFloat: gl.getUniformLocation(shaderProgram_cube, "move"),
			uSampler: gl.getUniformLocation(shaderProgram_cube, "uSampler"),//纹理采样 
		},
	};
	
	//顶点数组设置
	const cubehalflength = 0.578;
	const VAO_cube = cube_vao_gen(gl, cubehalflength, programInfo_cube);
	const VAO_dice20 = dice20_vao_gen(gl, programInfo_cube);
	const VAO_dice12 = dice12_vao_gen(gl, programInfo_cube);
	const VAO_dice10 = dice10_vao_gen(gl, programInfo_cube);
	const VAO_dice8 = dice8_vao_gen(gl, programInfo_cube);
	const VAO_dice4 = dice4_vao_gen(gl, programInfo_cube);
	
	// Load texture
	const texture = loadTexture(gl, `
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`);
	// Flip image pixels into the bottom-to-top order that WebGL expects.
	gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
	
	const texture_dice20 = loadTexture(gl, `
ZmlsZSB0eXBlIGV4aWYAAHjabVDbEcMgDPv3FB3BL8CMQxp61w06fk1MeqGt7pAc
K1GMob+eD7gNMCloKpZrzujQqpWbF4aBdjChHnyCJi99+JTsKq4ShuX51dmnJQap
eZUuQXafxrYaVUPZvoI4RMZEo95nUJ1BwmHQDGhxLczVyvUKW8cVFgcGqa1j/zwX
396e/D/C3IUEnUUsBpBxFKQNwxml+Isk2evkOvo2w3wh//Z0At7XMVkQ+/yT/AAA
AYRpQ0NQSUNDIHByb2ZpbGUAAHicfZE9SMNAHMVfU6WlVBzsoOKQoTpZBBVxlCoW
wUJpK7TqYHLpFzRpSFJcHAXXgoMfi1UHF2ddHVwFQfADxNnBSdFFSvxfUmgR48Fx
P97de9y9A4RmlalmzxygapaRTsTFXH5VDLwihACCmMCQxEw9mVnMwnN83cPH17sY
z/I+9+foUwomA3wi8RzTDYt4g3hm09I57xNHWFlSiM+Jxw26IPEj12WX3ziXHBZ4
ZsTIpueJI8RiqYvlLmZlQyWeJo4qqkb5Qs5lhfMWZ7VaZ+178heGC9pKhus0R5DA
EpJIQYSMOiqowkKMVo0UE2naj3v4hx1/ilwyuSpg5FhADSokxw/+B7+7NYtTk25S
OA70vtj2xygQ2AVaDdv+Prbt1gngfwautI6/1gRmP0lvdLToEdC/DVxcdzR5D7jc
AQafdMmQHMlPUygWgfcz+qY8MHALhNbc3tr7OH0AstTV8g1wcAiMlSh73ePdwe7e
/j3T7u8HsBFyv4b9/0AAAA12aVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8P3hw
YWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/
Pgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJY
TVAgQ29yZSA0LjQuMC1FeGl2MiI+CiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6
Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogIDxyZGY6
RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICB4bWxuczp4bXBNTT0iaHR0cDov
L25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIKICAgIHhtbG5zOnN0RXZ0PSJodHRw
Oi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiCiAg
ICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAg
ICB4bWxuczpHSU1QPSJodHRwOi8vd3d3LmdpbXAub3JnL3htcC8iCiAgICB4bWxu
czp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgIHhtbG5z
OnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIKICAgeG1wTU06RG9j
dW1lbnRJRD0iZ2ltcDpkb2NpZDpnaW1wOmRlMWIwMWE3LTQzN2ItNGUzZi1hMjBm
LTZhMzZmZjQxYzE3OSIKICAgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpkYjc1
Y2M1Yi04YjlmLTRjMTEtOTY5Ny0xN2VlMjk0MDMzMmMiCiAgIHhtcE1NOk9yaWdp
bmFsRG9jdW1lbnRJRD0ieG1wLmRpZDplOWFhNmFhMi1hOTllLTRhYzUtYWRmNS1k
Njg5MTFmOTE3N2IiCiAgIGRjOkZvcm1hdD0iaW1hZ2UvcG5nIgogICBHSU1QOkFQ
ST0iMi4wIgogICBHSU1QOlBsYXRmb3JtPSJXaW5kb3dzIgogICBHSU1QOlRpbWVT
dGFtcD0iMTcyODI5MTA5MTE2OTc2MCIKICAgR0lNUDpWZXJzaW9uPSIyLjEwLjM4
IgogICB0aWZmOk9yaWVudGF0aW9uPSIxIgogICB4bXA6Q3JlYXRvclRvb2w9IkdJ
TVAgMi4xMCIKICAgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyNDoxMDowN1QxNjo1MTox
OCswODowMCIKICAgeG1wOk1vZGlmeURhdGU9IjIwMjQ6MTA6MDdUMTY6NTE6MTgr
MDg6MDAiPgogICA8eG1wTU06SGlzdG9yeT4KICAgIDxyZGY6U2VxPgogICAgIDxy
ZGY6bGkKICAgICAgc3RFdnQ6YWN0aW9uPSJzYXZlZCIKICAgICAgc3RFdnQ6Y2hh
bmdlZD0iLyIKICAgICAgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDphMjVkYWIw
YS0yNjYxLTQ1MzQtOTE0ZS05YWVhYjhmYmRjNTUiCiAgICAgIHN0RXZ0OnNvZnR3
YXJlQWdlbnQ9IkdpbXAgMi4xMCAoV2luZG93cykiCiAgICAgIHN0RXZ0OndoZW49
IjIwMjQtMTAtMDdUMTY6NTE6MzEiLz4KICAgIDwvcmRmOlNlcT4KICAgPC94bXBN
TTpIaXN0b3J5PgogIDwvcmRmOkRlc2NyaXB0aW9uPgogPC9yZGY6UkRGPgo8L3g6
eG1wbWV0YT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIAo8P3hwYWNr
ZXQgZW5kPSJ3Ij8+w0/oewAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB+gK
BwgzH5bUKioAAAbGSURBVHja7d3dbqMwEAbQNOKZ8TP4qbtXrFLEj2kxjM05Ui/a
ZlUPY38YSLRf4zh+v4BHejsEIAAAAQAIAEAAAAIAEACAAAAEACAAAAEACABAAAAC
ABAAgAAABAAgAAABAAgAQAAAAgAQAEBtQ+0/kHP+8X1Kaff1e6+5w14dR+tUh3m1
V8f8d3Nn1PO+oriU0v/BLhWVc/7/FXmyrdWxVZM67ptXpQuplTpq+Kr1PwN9Frf1
88/v1/5NlCat/Xzp7BKtlifVsbb4W5xXtcd9+z2Az/TrUdSzT60tJW1xE7DSwrGY
YoRv632oPf7BNHFW7bGGlnZeR+s4sx8CwATsdvH0ugs7c2cjAEzA1bFPQRDx5mzv
W/+t4z09mQn/GNDZv+2J1/sNWuwAqi1+C+fe47/2nga9sQOw+MEOwOJ/ynVzi73Z
68dZtbxrN6L2Y4yrJtRWHfO30y59Ra/j86Zf5MXzlHm114+zVHsr8JEmrRUV7e2n
pQ2MWsteP1pZVE+YV1f1o2oAALG5CQgCABAAgAAABAAgAAABAAgAQAAAAgAQAIAA
AAQAIAAAAQAIAEAAAAIAEACAAAAEACAAAAEACABAAAACABAAgAAABAAgAAABAAgA
QAAAAgAQAMAPQ+0/kHP+8X1KqfjflLz2Knt1zH+/JEI9Jf34Tc8i1tFKLdM4t8ZW
q46vcRy/azdpGuzewv4sMuLi36qjhQAorWOprtb60UItR0OsdB2FuARYGuS8gLXX
R55sW3VMY59/RVz8S3Us9WWrZ5H7Eb2W0kV8dB2FuwQ4Iur27MyUh0hz/W2R1G9o
D8HWUg1Ct6EAiHiN+fSJmHP+cVnQWm96nEu1DJEXizPnPWPduieAALh0ArYaAq2O
fe0Gbct9IPg9gPmZsvUzf8tb/+n4z5/GtFbT0tMklwbBdwA9aXWyLS2als+iFn0j
O4BetH72f0JvhIIA4GFnSov/4gDYerdSyfvPozTrSB2RJ1lpHWs7gSg1HZ1XrS/+
39R7xCWfBWh18R8ZX9TPMfyljqj1/GZetfCBpjt6UjUAAPcAAAEACABAAAACABAA
gAAABAAgAAABAAgAQAAAAgAQAIAAAAQAIAAAAQAIAEAAAAIAEACAAAABAAgAQAAA
AgAQAIAAAAQAIAAAAQAIAEAAAAIAaMhw1R/KOb9SSqe97i5r48s5//g+cg1PqKOH
eTXvxdwZ9Qy1izrzdXc25+jvp59FmnRPqaOV+RVhXEPt4lJKm4WWvu7uJu2N72h6
q6NuHa0s/pI6aoZvtQAoHXT0LeZfxxdl61kyhui9aGWMLdXhJmClZvYyUVsW/bo/
QlAMpokzVo81RL+v9Jc6zuyHADABu108ve7CztzZCAATcHXsUxBEfBLQ+9Z/63jn
nE+r0T0AZ9DViZdSci+jc3YAlRa/hXPv8W/lPQ13swOw+LED4OmLv+fr5hZ7s9cP
NwGDXvOvXf+38Ianrfej29XE6sdZvsZx/L5iYWwthuiLZmt8pQ2JUMveca79zNm8
itePqgEAxOYmIAgAQAAAAgAQAIAAAAQAIAAAAQAIAEAAAAIAEACAAAAEACAAAAEA
CABAAAACABAAgAAABAAgAAABAAgAQAAAAgAQAIAAAAQAIAAAAQAIAEAAAD8MV/2h
nPMrpVT82tfrVfz6K63VMY15S6R6tvoxryViH0rnVdRajo6rVh3DlUUeeX20xdKD
kjrmCyrnfCi8I/Ujai1L49866c1/d2Yd79pF/uasH3GylYxpGvv8K0KgldSxNDE/
J11L/Yhey9IcKa33zDqGmgVe8W+uaFQPu4fI2/gn1nHGpfIZ3lGK7nli9jBpW6oh
+nxaOpZ3Hd93lGb1mOytBtt0jXnHGenpu4Srxz5EXizOnPeM9XPx0/fJYog+AVsN
gVbHvnaHuuU+OFkEvwcwL771M3/LW//p+M/vTrdW09Ld9ajz6s5jO7xwHbox7pRS
05cC0ftw9z0wbwV29n/M9X60G84RxiMA6OKyy+JvPAB6eArQwyPNtZ1ADzVF/BzA
9Mh1/jU/7rXWx9c4jt93T6boi7+kjqifY/hLHVHr+c28ivohoJIdWc2eVA0AIDb3
AEAAAAIAEACAAAAEACAAAAEACABAAAACABAAgAAABAAgAAABAAgAQAAAAgAQAIAA
AAQAIAAAAQAIAEAAAAIAEACAAAAEACAAAAEACABAAAACABAAgAAAAeAQgAAABAAg
AAABAAgAQAAAAgAQAIAAAAQAIAAAAQAIAEAAAAIAEACAAAAEACAAAAEACABAAAAC
ABAAgAAABAAgAAABAAgA4KB/VCdCfkhXkAoAAAAASUVORK5CYII=`);
	// Flip image pixels into the bottom-to-top order that WebGL expects.
	gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);

	

	


	
	
	//------
	
	//地面边界的顶点属性
	const ground_length = 7;
	const VAO_ground = gl.createVertexArray();
	gl.bindVertexArray(VAO_ground);
	const VBO_ground = gl.createBuffer();
	gl.bindBuffer(gl.ARRAY_BUFFER, VBO_ground);
	{
	let ground = [
		ground_length, 0, ground_length, 0, 1, 0,
		-ground_length, 0, ground_length, 0, 1, 0,
		-ground_length, 0, -ground_length, 0, 1, 0,
		
		ground_length, 0, ground_length, 0, 1, 0,
		-ground_length, 0, -ground_length, 0, 1, 0,
		ground_length, 0, -ground_length, 0, 1, 0,
		
		ground_length, ground_length, ground_length, -1, 0, 0, 
		ground_length, ground_length, -ground_length, -1, 0, 0,
		ground_length, 0, -ground_length, -1, 0, 0, 
		ground_length, ground_length, ground_length, -1, 0, 0, 
		ground_length, 0, -ground_length, -1, 0, 0, 
		ground_length, 0, ground_length, -1, 0, 0, 
		
		ground_length, ground_length, -ground_length, 0, 0, 1, 
		-ground_length, ground_length, -ground_length, 0, 0, 1, 
		-ground_length, 0, -ground_length, 0, 0, 1, 
		ground_length, ground_length, -ground_length, 0, 0, 1, 
		-ground_length, 0, -ground_length, 0, 0, 1, 
		ground_length, 0, -ground_length, 0, 0, 1, 
		
		-ground_length, ground_length, -ground_length, 1, 0, 0, 
		-ground_length, ground_length, ground_length, 1, 0, 0, 
		-ground_length, 0, ground_length, 1, 0, 0, 
		-ground_length, ground_length, -ground_length, 1, 0, 0, 
		-ground_length, 0, ground_length, 1, 0, 0, 
		-ground_length, 0, -ground_length, 1, 0, 0, 
		
		-ground_length, ground_length, ground_length, 0, 0, -1, 
		ground_length, ground_length, ground_length, 0, 0, -1, 
		ground_length, 0, ground_length, 0, 0, -1, 
		-ground_length, ground_length, ground_length, 0, 0, -1, 
		ground_length, 0, ground_length, 0, 0, -1, 
		-ground_length, 0, ground_length, 0, 0, -1, 
	];//顶点数据
		
	gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(ground), gl.STATIC_DRAW);
	}
	//顶点属性
	const programInfo_ground = {
		program: shaderProgram_ground,
		attribLocations: {
			vertexPosition: gl.getAttribLocation(shaderProgram_ground, "aPos"),
			normPosition: gl.getAttribLocation(shaderProgram_ground, "norm"),
		},
		uniformLocations: {
			projectionMatrix: gl.getUniformLocation(shaderProgram_ground, "pers"),
			rotateMatrix: gl.getUniformLocation(shaderProgram_ground, "rota"),
			moveFloat: gl.getUniformLocation(shaderProgram_ground, "move"),
		},
	};
	gl.vertexAttribPointer(
		programInfo_ground.attribLocations.vertexPosition,
		3,
		gl.FLOAT,
		false,
		24,
		0,
	);
	gl.vertexAttribPointer(
		programInfo_ground.attribLocations.normPosition,
		3,
		gl.FLOAT,
		false,
		24,
		12,
	);
	gl.enableVertexAttribArray(programInfo_ground.attribLocations.vertexPosition);
	gl.enableVertexAttribArray(programInfo_ground.attribLocations.normPosition);
	
	//箭头顶点属性
	/*
	const VAO_arrow = gl.createVertexArray();
	gl.bindVertexArray(VAO_arrow);
	const VBO_arrow = gl.createBuffer();
	gl.bindBuffer(gl.ARRAY_BUFFER, VBO_arrow);
	{
	let arrow = [
		2.0, 1.0, 1.0, 0.707, 0.707, 0.0,
		3.0, 0.0, 0.0, 0.707, 0.707, 0.0,
		2.0, 1.0, -1.0, 0.707, 0.707, 0.0,
		
		2.0, 1.0, -1.0, 0.707, 0.0, -0.707,
		3.0, 0.0, 0.0, 0.707, 0.0, -0.707,
		2.0, -1.0, -1.0, 0.707, 0.0, -0.707,
		
		2.0, -1.0, -1.0, 0.707, -0.707, 0.0,
		3.0, 0.0, 0.0, 0.707, -0.707, 0.0,
		2.0, -1.0, 1.0, 0.707, -0.707, 0.0,
		
		2.0, -1.0, 1.0, 0.707, 0.0, 0.707,
		3.0, 0.0, 0.0, 0.707, 0.0, 0.707,
		2.0, 1.0, 1.0, 0.707, 0.0, 0.707,
		
		2.0, 1.0, 1.0, -1.0, 0.0, 0.0,
		2.0, 1.0, -1.0, -1.0, 0.0, 0.0,
		2.0, -1.0, 1.0, -1.0, 0.0, 0.0,
		
		2.0, 1.0, -1.0, -1.0, 0.0, 0.0,
		2.0, -1.0, -1.0, -1.0, 0.0, 0.0,
		2.0, -1.0, 1.0, -1.0, 0.0, 0.0,
	];//箭头的顶点数据
	
	
	gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(arrow), gl.STATIC_DRAW);
	}


		
	//顶点属性
	const programInfo_arrow = {
		program: shaderProgram_arrow,
		attribLocations: {
			vertexPosition: gl.getAttribLocation(shaderProgram_arrow, "aPos"),
			normPosition: gl.getAttribLocation(shaderProgram_arrow, "norm"),
		},
		uniformLocations: {
			projectionMatrix: gl.getUniformLocation(shaderProgram_arrow, "pers"),
			rotateMatrix: gl.getUniformLocation(shaderProgram_arrow, "rota"),
			partrotateMatrix: gl.getUniformLocation(shaderProgram_arrow, "partrota"),//局部坐标旋转与平移矩阵
			moveVec: gl.getUniformLocation(shaderProgram_arrow, "move"),
		},
	};
	gl.vertexAttribPointer(
		programInfo_arrow.attribLocations.vertexPosition,
		3,
		gl.FLOAT,
		false,
		24,
		0,
	);
	gl.vertexAttribPointer(
		programInfo_arrow.attribLocations.normPosition,
		3,
		gl.FLOAT,
		false,
		24,
		12,
	);
	gl.enableVertexAttribArray(programInfo_arrow.attribLocations.vertexPosition);
	gl.enableVertexAttribArray(programInfo_arrow.attribLocations.normPosition);
	*/
	
	//global
	var TRANSFORM_AUX = new Ammo.btTransform();
	
	// Physics variables
	var collisionConfiguration;
	var dispatcher;
	var broadphase;
	var solver;
	var physicsWorld;

	var time = 0;
	
	// Physics configuration
	collisionConfiguration = new Ammo.btDefaultCollisionConfiguration();
	dispatcher = new Ammo.btCollisionDispatcher( collisionConfiguration );
	broadphase = new Ammo.btDbvtBroadphase();
	solver = new Ammo.btSequentialImpulseConstraintSolver();
	physicsWorld = new Ammo.btDiscreteDynamicsWorld( dispatcher, broadphase, solver, collisionConfiguration );
	physicsWorld.setGravity( new Ammo.btVector3( 0, -10, 0 ) );
	
	//
	function createBox(pos, quat, w, l, h, mass, friction) {

				var geometry = new Ammo.btBoxShape(new Ammo.btVector3(w * 0.5, l * 0.5, h * 0.5));

				if(!mass) mass = 0;
				if(!friction) friction = 1;

				var transform = new Ammo.btTransform();
				transform.setIdentity();
				transform.setOrigin(new Ammo.btVector3(pos[0], pos[1], pos[2]));
				transform.setRotation(new Ammo.btQuaternion(quat[0], quat[1], quat[2], quat[3]));
				var motionState = new Ammo.btDefaultMotionState(transform);

				var localInertia = new Ammo.btVector3(0, 0, 0);
				geometry.calculateLocalInertia(mass, localInertia);

				var rbInfo = new Ammo.btRigidBodyConstructionInfo(mass, motionState, geometry, localInertia);
				//恢复系数 偏向弹性碰撞
				rbInfo.m_restitution = 0.5;
				var body = new Ammo.btRigidBody(rbInfo);

				body.setFriction(friction);
				//body.setRestitution(.9);
				//body.setDamping(0.2, 0.2);

				physicsWorld.addRigidBody( body );
				
				if (mass > 0) {
					body.setActivationState(4);
				}
				
				return body;
			}
		
	//dice12刚体生成
	function createDice12(pos, quat, mass, friction) {

				//var geometry = new Ammo.btBoxShape(new Ammo.btVector3(w * 0.5, l * 0.5, h * 0.5));
				const phi = 1.618 / 1.732;//同下
				const phi_1 = 1 / 1.618 / 1.732;
				const length_m = 1.0 / 1.732;//正方体坐标缩放
				let vertex = [
					phi_1, 0, phi, 
					-phi_1, 0, phi, 
					-phi_1, 0, -phi, 
					phi_1, 0, -phi, 
		
					phi, phi_1, 0, 
					-phi, phi_1, 0, 
					-phi, -phi_1, 0, 
					phi, -phi_1, 0, 
		
					0, phi, phi_1, 
					0, -phi, phi_1, 
					0, -phi, -phi_1, 
					0, phi, -phi_1,

					length_m, length_m, length_m,
					-length_m, length_m, length_m,
					length_m, -length_m, length_m,
					-length_m, -length_m, length_m,
					length_m, length_m, -length_m,
					-length_m, length_m, -length_m,
					length_m, -length_m, -length_m,
					-length_m, -length_m, -length_m,
				];
				//let geometry = new Ammo.btConvexHullShape(new Float32Array(vertex), 12, 12);
				
				let geometry = new Ammo.btConvexHullShape([0,0,0], 0, 12);
				for(let i  = 0;i < 20;i += 1){
					geometry.addPoint(new Ammo.btVector3(vertex[0 + i*3], vertex[1 + i*3], vertex[2 + i*3]));
				}
				
				//geometry.initializePolyhedralFeatures();//格式化

				if(!mass) mass = 0;
				if(!friction) friction = 1;

				var transform = new Ammo.btTransform();
				transform.setIdentity();
				transform.setOrigin(new Ammo.btVector3(pos[0], pos[1], pos[2]));
				transform.setRotation(new Ammo.btQuaternion(quat[0], quat[1], quat[2], quat[3]));
				var motionState = new Ammo.btDefaultMotionState(transform);

				var localInertia = new Ammo.btVector3(0, 0, 0);
				geometry.calculateLocalInertia(mass, localInertia);

				var rbInfo = new Ammo.btRigidBodyConstructionInfo(mass, motionState, geometry, localInertia);
				//恢复系数 偏向弹性碰撞
				rbInfo.m_restitution = 0.5;
				var body = new Ammo.btRigidBody(rbInfo);

				body.setFriction(friction);
				//body.setRestitution(.9);
				//body.setDamping(0.2, 0.2);

				physicsWorld.addRigidBody( body );
				
				if (mass > 0) {
					body.setActivationState(4);
				}
				
				return body;
			}
			
			
	//dice20刚体生成
	function createDice20(pos, quat, mass, friction) {

				//var geometry = new Ammo.btBoxShape(new Ammo.btVector3(w * 0.5, l * 0.5, h * 0.5));
				let m = 0.52573;
				let n = 0.85065;
				let vertex = [
					0.0, n, m, 
					0.0, n, -m, 
					0.0, -n, -m, 
					0.0, -n, m, 
		
					n, m, 0.0, 
					-n, m, 0.0, 
					-n, -m, 0.0, 
					n, -m, 0.0, 
		
					m, 0.0, n, 
					-m, 0.0, n, 
					-m, 0.0, -n, 
					m, 0.0, -n, 
				];
				//let geometry = new Ammo.btConvexHullShape(new Float32Array(vertex), 12, 12);
				
				let geometry = new Ammo.btConvexHullShape([0,0,0], 0, 12);
				for(let i  = 0;i < 12;i += 1){
					geometry.addPoint(new Ammo.btVector3(vertex[0 + i*3], vertex[1 + i*3], vertex[2 + i*3]));
				}
				
				//geometry.initializePolyhedralFeatures();//格式化

				if(!mass) mass = 0;
				if(!friction) friction = 1;

				var transform = new Ammo.btTransform();
				transform.setIdentity();
				transform.setOrigin(new Ammo.btVector3(pos[0], pos[1], pos[2]));
				transform.setRotation(new Ammo.btQuaternion(quat[0], quat[1], quat[2], quat[3]));
				var motionState = new Ammo.btDefaultMotionState(transform);

				var localInertia = new Ammo.btVector3(0, 0, 0);
				geometry.calculateLocalInertia(mass, localInertia);

				var rbInfo = new Ammo.btRigidBodyConstructionInfo(mass, motionState, geometry, localInertia);
				//恢复系数 偏向弹性碰撞
				rbInfo.m_restitution = 0.5;
				var body = new Ammo.btRigidBody(rbInfo);

				body.setFriction(friction);
				//body.setRestitution(.9);
				//body.setDamping(0.2, 0.2);

				physicsWorld.addRigidBody( body );
				
				if (mass > 0) {
					body.setActivationState(4);
				}
				
				return body;
			}
			
	//dice10刚体生成
	function createDice10(pos, quat, mass, friction) {

				//var geometry = new Ammo.btBoxShape(new Ammo.btVector3(w * 0.5, l * 0.5, h * 0.5));
				let radial = 1.0;
				const tmp = radial - 0.1056 * radial;

				let vertex = [
					0, radial, 0, 	
		
					tmp, 0.1056*radial, 0, 		
		
					tmp*0.809, -0.1056*radial, tmp*0.588, 	
		
					tmp*0.309, 0.1056*radial, tmp*0.951, 	
		
					tmp*-0.309, -0.1056*radial, tmp*0.951, 
		
					tmp*-0.809, 0.1056*radial, tmp*0.588, 	
		
					-tmp, -0.1056*radial, 0,			 
		
					tmp*-0.809, 0.1056*radial, tmp*-0.588, 
		
					tmp*-0.309, -0.1056*radial, tmp*-0.951, 	
		
					tmp*0.309, 0.1056*radial, tmp*-0.951, 	
		
					tmp*0.809, -0.1056*radial, tmp*-0.588, 	
					
					0, -radial, 0, 

				];
				//let geometry = new Ammo.btConvexHullShape(new Float32Array(vertex), 12, 12);
				
				let geometry = new Ammo.btConvexHullShape([0,0,0], 0, 12);
				for(let i  = 0;i < 12;i += 1){
					geometry.addPoint(new Ammo.btVector3(vertex[0 + i*3], vertex[1 + i*3], vertex[2 + i*3]));
				}
				
				//geometry.initializePolyhedralFeatures();//格式化

				if(!mass) mass = 0;
				if(!friction) friction = 1;

				var transform = new Ammo.btTransform();
				transform.setIdentity();
				transform.setOrigin(new Ammo.btVector3(pos[0], pos[1], pos[2]));
				transform.setRotation(new Ammo.btQuaternion(quat[0], quat[1], quat[2], quat[3]));
				var motionState = new Ammo.btDefaultMotionState(transform);

				var localInertia = new Ammo.btVector3(0, 0, 0);
				geometry.calculateLocalInertia(mass, localInertia);

				var rbInfo = new Ammo.btRigidBodyConstructionInfo(mass, motionState, geometry, localInertia);
				//恢复系数 偏向弹性碰撞
				rbInfo.m_restitution = 0.5;
				var body = new Ammo.btRigidBody(rbInfo);

				body.setFriction(friction);
				//body.setRestitution(.9);
				//body.setDamping(0.2, 0.2);

				physicsWorld.addRigidBody( body );
				
				if (mass > 0) {
					body.setActivationState(4);
				}
				
				return body;
			}
	
			
	//dice8刚体生成
	function createDice8(pos, quat, mass, friction) {

				//var geometry = new Ammo.btBoxShape(new Ammo.btVector3(w * 0.5, l * 0.5, h * 0.5));
				let length = 1.0;

				let vertex = [
					0, length, 0, 
					length, 0, 0, 
					0, 0, length, 
					
					0, -length, 0, 
					-length, 0, 0, 
					0, 0, -length, 
		

				];
				//let geometry = new Ammo.btConvexHullShape(new Float32Array(vertex), 12, 12);
				
				let geometry = new Ammo.btConvexHullShape([0,0,0], 0, 12);
				for(let i  = 0;i < 6;i += 1){
					geometry.addPoint(new Ammo.btVector3(vertex[0 + i*3], vertex[1 + i*3], vertex[2 + i*3]));
				}
				
				//geometry.initializePolyhedralFeatures();//格式化

				if(!mass) mass = 0;
				if(!friction) friction = 1;

				var transform = new Ammo.btTransform();
				transform.setIdentity();
				transform.setOrigin(new Ammo.btVector3(pos[0], pos[1], pos[2]));
				transform.setRotation(new Ammo.btQuaternion(quat[0], quat[1], quat[2], quat[3]));
				var motionState = new Ammo.btDefaultMotionState(transform);

				var localInertia = new Ammo.btVector3(0, 0, 0);
				geometry.calculateLocalInertia(mass, localInertia);

				var rbInfo = new Ammo.btRigidBodyConstructionInfo(mass, motionState, geometry, localInertia);
				//恢复系数 偏向弹性碰撞
				rbInfo.m_restitution = 0.5;
				var body = new Ammo.btRigidBody(rbInfo);

				body.setFriction(friction);
				//body.setRestitution(.9);
				//body.setDamping(0.2, 0.2);

				physicsWorld.addRigidBody( body );
				
				if (mass > 0) {
					body.setActivationState(4);
				}
				
				return body;
			}
			
	//dice4刚体生成
	function createDice4(pos, quat, mass, friction) {

				//var geometry = new Ammo.btBoxShape(new Ammo.btVector3(w * 0.5, l * 0.5, h * 0.5));
				const length = 1.0;
				const tmp = length*0.943;

				let vertex = [
					0, length, 0, 	
					tmp, -length/3, 0, 	
					-tmp/2, -length/3, tmp*0.866,
					-tmp/2, -length/3, -tmp*0.866,

				];
				//let geometry = new Ammo.btConvexHullShape(new Float32Array(vertex), 12, 12);
				
				let geometry = new Ammo.btConvexHullShape([0,0,0], 0, 12);
				for(let i  = 0;i < 4;i += 1){
					geometry.addPoint(new Ammo.btVector3(vertex[0 + i*3], vertex[1 + i*3], vertex[2 + i*3]));
				}
				
				//geometry.initializePolyhedralFeatures();//格式化

				if(!mass) mass = 0;
				if(!friction) friction = 1;

				var transform = new Ammo.btTransform();
				transform.setIdentity();
				transform.setOrigin(new Ammo.btVector3(pos[0], pos[1], pos[2]));
				transform.setRotation(new Ammo.btQuaternion(quat[0], quat[1], quat[2], quat[3]));
				var motionState = new Ammo.btDefaultMotionState(transform);

				var localInertia = new Ammo.btVector3(0, 0, 0);
				geometry.calculateLocalInertia(mass, localInertia);

				var rbInfo = new Ammo.btRigidBodyConstructionInfo(mass, motionState, geometry, localInertia);
				//恢复系数 偏向弹性碰撞
				rbInfo.m_restitution = 0.5;
				var body = new Ammo.btRigidBody(rbInfo);

				body.setFriction(friction);
				//body.setRestitution(.9);
				//body.setDamping(0.2, 0.2);

				physicsWorld.addRigidBody( body );
				
				if (mass > 0) {
					body.setActivationState(4);
				}
				
				return body;
			}
	
	
	//改变骰子速度
	function shake(body_array){
		for(let i = 0;i < body_array.length;i += 1){
			body_array[i].setLinearVelocity(new Ammo.btVector3(0, 15, 0));
			body_array[i].setAngularVelocity(new Ammo.btVector3(10, 10, 0));
		}
	}		
	
	//删除刚体
	function removeallbody(body_array){
		for(let i = 0;i < body_array.length;i += 1){
			physicsWorld.removeRigidBody( body_array[i] );
		}

	}
			
	
	//存储不同骰子刚体的数组
	let body_dice6 = [];	
	let body_dice12 = [];	
	let body_dice20 = [];
	let body_dice10 = [];	
	let body_dice8 = [];	
	let body_dice4 = [];	
			
	//create objects
	const size = cubehalflength * 2;
	body_dice6.push(createBox([0.0 ,1.0, 0.0], [0.0, 0 ,0.0, 1.0], size, size, size, 10, 0.7));
			
	createBox([0.0 ,-0.5, 0.0], [0, 0, 0, 1], ground_length*2, 1, ground_length*2, 0, 1);
			
	createBox([ground_length, 0.0, 0.0], [0, 0, 0, 1], 1, ground_length*2, ground_length*2, 0, 1);
	createBox([-ground_length , 0.0, 0.0], [0, 0, 0, 1], 1, ground_length*2, ground_length*2, 0, 1);
	createBox([0.0 , 0.0, ground_length], [0, 0, 0, 1], ground_length*2, ground_length*2, 1, 0, 1);
	createBox([0.0 ,0.0, -ground_length], [0, 0, 0, 1], ground_length*2, ground_length*2, 1, 0, 1);
	createBox([0.0 ,ground_length, 0.0], [0, 0, 0, 1], ground_length*2, 1, ground_length*2, 0, 1);
			
	//let dice20 = createDice20([0.0 ,1.0, 0.0], [0.0, 0 ,0.0, 1.0], 10, 0.7)

		
	//texture set
	// Tell WebGL we want to affect texture unit 0
	gl.activeTexture(gl.TEXTURE0);
	// Bind the texture to texture unit 0
	gl.bindTexture(gl.TEXTURE_2D, texture);
	// Tell WebGL we want to affect texture unit 1
	gl.activeTexture(gl.TEXTURE1);
	// Bind the texture to texture unit 0
	gl.bindTexture(gl.TEXTURE_2D, texture_dice20);

	function render(now) {

		
		//物理引擎计算
		physicsWorld.stepSimulation( 1.0/60.0, 10 );
		
		

		
		//按键控制
		if(w_down == 1)
			position_move(move_speed, 0, angle_xz);
		if(s_down == 1)
			position_move(-move_speed, 0, angle_xz);
		if(a_down == 1)
			position_move(0, move_speed, angle_xz);
		if(d_down == 1)
			position_move(0, -move_speed, angle_xz);
		if(q_down == 1)
			move_y += move_speed;
		if(e_down == 1){
			move_y -= move_speed;
			
		}
		if(f_down == 1){
			//test 改变运动状态
			shake(body_dice4);
			shake(body_dice6);
			shake(body_dice8);
			shake(body_dice10);
			shake(body_dice12);
			shake(body_dice20);
			
			/*
			for(let i = 0;i < body_dice6.length;i += 1){
				body_dice6[i].setLinearVelocity(new Ammo.btVector3(0, 15, 0));
				body_dice6[i].setAngularVelocity(new Ammo.btVector3(10, 10, 0));
			}
			
			for(let i = 0;i < body_dice20.length;i += 1){
				body_dice20[i].setLinearVelocity(new Ammo.btVector3(0, 15, 0));
				body_dice20[i].setAngularVelocity(new Ammo.btVector3(10, 10, 0));
			}
			
			for(let i = 0;i < body_dice12.length;i += 1){
				body_dice12[i].setLinearVelocity(new Ammo.btVector3(0, 15, 0));
				body_dice12[i].setAngularVelocity(new Ammo.btVector3(10, 10, 0));
			}
			
			for(let i = 0;i < body_dice10.length;i += 1){
				body_dice10[i].setLinearVelocity(new Ammo.btVector3(0, 15, 0));
				body_dice10[i].setAngularVelocity(new Ammo.btVector3(10, 10, 0));
			}
			
			for(let i = 0;i < body_dice8.length;i += 1){
				body_dice8[i].setLinearVelocity(new Ammo.btVector3(0, 15, 0));
				body_dice8[i].setAngularVelocity(new Ammo.btVector3(10, 10, 0));
			}
			*/
			
			/*
			cube.setLinearVelocity(new Ammo.btVector3(0, 15, 0));
			cube.setAngularVelocity(new Ammo.btVector3(3, 3, 0));
			dice20.setLinearVelocity(new Ammo.btVector3(0, 15, 0));
			dice20.setAngularVelocity(new Ammo.btVector3(3, 3, 0));
			*/
			
			//cube.setGravity(new Ammo.btVector3(0, 5, 0));//test
			f_down = 0;
		}
		
		
		//根据设置更改骰子类型和数量
		if(reset == 1){
			reset = 0;
			
			//清除所有body
			removeallbody(body_dice4);
			body_dice4=[];
			
			removeallbody(body_dice6);
			body_dice6=[];
			
			removeallbody(body_dice8);
			body_dice8=[];
			
			removeallbody(body_dice10);
			body_dice10=[];
			
			removeallbody(body_dice12);
			body_dice12=[];
			
			removeallbody(body_dice20);
			body_dice20=[];

			/*
			for(let i = 0;i < body_dice6.length;i += 1){
				physicsWorld.removeRigidBody( body_dice6[i] );
			}
			body_dice6 = [];
			
			for(let i = 0;i < body_dice20.length;i += 1){
				physicsWorld.removeRigidBody( body_dice20[i] );
			}
			body_dice20 = [];
			
			for(let i = 0;i < body_dice12.length;i += 1){
				physicsWorld.removeRigidBody( body_dice12[i] );
			}
			body_dice12 = [];
			
			for(let i = 0;i < body_dice10.length;i += 1){
				physicsWorld.removeRigidBody( body_dice10[i] );
			}
			body_dice10 = [];
			*/
			
			//获取数量
			let num_dice6 = parseFloat(d6.value);
			let num_dice12 = parseFloat(d12.value);
			let num_dice20 = parseFloat(d20.value);
			let num_dice10 = parseFloat(d10.value);
			let num_dice8 = parseFloat(d8.value);
			let num_dice4 = parseFloat(d4.value);
			
			//添加body
			for(let i = 0;i < num_dice6;i += 1){
				body_dice6.push(createBox([0.0 ,2.0, 0.0], [0.0, 0 ,0.0, 1.0], size, size, size, 10, 0.7));
			}
			for(let i = 0;i < num_dice20;i += 1){
				body_dice20.push(createDice20([0.0 ,2.0, 0.0], [0.0, 0 ,0.0, 1.0], 10, 0.7));
			}
			for(let i = 0;i < num_dice12;i += 1){
				body_dice12.push(createDice12([0.0 ,2.0, 0.0], [0.0, 0 ,0.0, 1.0], 10, 0.7));
			}
			for(let i = 0;i < num_dice10;i += 1){
				body_dice10.push(createDice10([0.0 ,2.0, 0.0], [0.0, 0 ,0.0, 1.0], 10, 0.7));
			}
			for(let i = 0;i < num_dice8;i += 1){
				body_dice8.push(createDice8([0.0 ,2.0, 0.0], [0.0, 0 ,0.0, 1.0], 10, 0.7));
			}
			for(let i = 0;i < num_dice4;i += 1){
				body_dice4.push(createDice4([0.0 ,2.0, 0.0], [0.0, 0 ,0.0, 1.0], 10, 0.7));
			}
		}
		
		
		
		const perspec = [
		1.0, 0.0, 0.0, 0.0, 0.0, screen_width/screen_height, 0.0, 0.0, 0.0, 0.0, -1.001, -1.0, 0.0, 0.0, -0.21, 0.0];
		
					
		
		//const rotate_cube = quad2matrix(0.707, 0 ,0.707, 0);//test
		
		const xz_sin = Math.sin(angle_xz);
		const xz_cos = Math.cos(angle_xz);
		const y_sin = Math.sin(angle_y);
		const y_cos = Math.cos(angle_y);

		const rotate = rotate_matrix(xz_sin, xz_cos, y_sin, y_cos);//旋转矩阵


		gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
		

	
		//渲染cube
		gl.bindVertexArray(VAO_cube);
		gl.useProgram(programInfo_cube.program);
		gl.uniformMatrix4fv(
			programInfo_cube.uniformLocations.projectionMatrix,
			false,
			new Float32Array(perspec),
		);
		gl.uniformMatrix4fv(
			programInfo_cube.uniformLocations.rotateMatrix,
			false,
			new Float32Array(rotate),
		);
		
		
		//gl.uniform3f(programInfo_cube.uniformLocations.moveFloat, - move_x, -move_y , - move_z);//移动
		//test
		//console.log("world pos = " + p.x().toString(10));
		
		// Tell the shader we bound the texture to texture unit 0
		gl.uniform1i(programInfo_cube.uniformLocations.uSampler, 0);
		//循环渲染多个body
		for(let i = 0;i < body_dice6.length;i += 1){
			//获取运动状态
			body_dice6[i].getMotionState().getWorldTransform(TRANSFORM_AUX);
			
			let p = TRANSFORM_AUX.getOrigin();
			let q = TRANSFORM_AUX.getRotation();
			
			//用于局部坐标旋转的矩阵
			const rotate_cube = quad2matrix(q.x(), q.y(), q.z(), q.w());
			
			//uniform更新
			gl.uniform3f(programInfo_cube.uniformLocations.moveFloat, - move_x + p.x(), -move_y + p.y(), - move_z + p.z());//移动
			gl.uniformMatrix4fv(
				programInfo_cube.uniformLocations.partrotateMatrix,
				false,
				new Float32Array(rotate_cube),
			);
			
			gl.drawArrays(gl.TRIANGLES, 0, 6 * 6);
		}
		
		
		
		
		//渲染dice20
		//获取运动状态
		/*
		dice20.getMotionState().getWorldTransform(TRANSFORM_AUX);
		p = TRANSFORM_AUX.getOrigin();
		q = TRANSFORM_AUX.getRotation();
		
		const rotate_dice20 = quad2matrix(q.x(), q.y(), q.z(), q.w());
		gl.uniform3f(programInfo_cube.uniformLocations.moveFloat, - move_x + p.x(), -move_y + p.y(), - move_z + p.z());//移动
		gl.uniformMatrix4fv(
			programInfo_cube.uniformLocations.partrotateMatrix,
			false,
			new Float32Array(rotate_dice20),
		);
		*/
		gl.uniform1i(programInfo_cube.uniformLocations.uSampler, 1);
		gl.bindVertexArray(VAO_dice20);
		
		//循环渲染多个dice20 body
		for(let i = 0;i < body_dice20.length;i += 1){
			//获取运动状态
			body_dice20[i].getMotionState().getWorldTransform(TRANSFORM_AUX);
			
			let p = TRANSFORM_AUX.getOrigin();
			let q = TRANSFORM_AUX.getRotation();
			
			//用于局部坐标旋转的矩阵
			const rotate_cube = quad2matrix(q.x(), q.y(), q.z(), q.w());
			
			//uniform更新
			gl.uniform3f(programInfo_cube.uniformLocations.moveFloat, - move_x + p.x(), -move_y + p.y(), - move_z + p.z());//移动
			gl.uniformMatrix4fv(
				programInfo_cube.uniformLocations.partrotateMatrix,
				false,
				new Float32Array(rotate_cube),
			);
			
			gl.drawArrays(gl.TRIANGLES, 0, 3 * 20);
		}
		
		
		//dice12
		gl.uniform1i(programInfo_cube.uniformLocations.uSampler, 1);
		gl.bindVertexArray(VAO_dice12);
		//循环渲染多个dice12 body
		for(let i = 0;i < body_dice12.length;i += 1){
			//获取运动状态
			body_dice12[i].getMotionState().getWorldTransform(TRANSFORM_AUX);
			
			let p = TRANSFORM_AUX.getOrigin();
			let q = TRANSFORM_AUX.getRotation();
			
			//用于局部坐标旋转的矩阵
			const rotate_cube = quad2matrix(q.x(), q.y(), q.z(), q.w());
			
			//uniform更新
			gl.uniform3f(programInfo_cube.uniformLocations.moveFloat, - move_x + p.x(), -move_y + p.y(), - move_z + p.z());//移动
			gl.uniformMatrix4fv(
				programInfo_cube.uniformLocations.partrotateMatrix,
				false,
				new Float32Array(rotate_cube),
			);
			
			gl.drawArrays(gl.TRIANGLES, 0, 3 * 3 * 12);
		}
		
		//dice10
		gl.uniform1i(programInfo_cube.uniformLocations.uSampler, 1);
		gl.bindVertexArray(VAO_dice10);
		//循环渲染多个dice10 body
		for(let i = 0;i < body_dice10.length;i += 1){
			//获取运动状态
			body_dice10[i].getMotionState().getWorldTransform(TRANSFORM_AUX);
			
			let p = TRANSFORM_AUX.getOrigin();
			let q = TRANSFORM_AUX.getRotation();
			
			//用于局部坐标旋转的矩阵
			const rotate_cube = quad2matrix(q.x(), q.y(), q.z(), q.w());
			
			//uniform更新
			gl.uniform3f(programInfo_cube.uniformLocations.moveFloat, - move_x + p.x(), -move_y + p.y(), - move_z + p.z());//移动
			gl.uniformMatrix4fv(
				programInfo_cube.uniformLocations.partrotateMatrix,
				false,
				new Float32Array(rotate_cube),
			);
			
			gl.drawArrays(gl.TRIANGLES, 0, 3 * 20);
		}
		
		//dice8
		gl.uniform1i(programInfo_cube.uniformLocations.uSampler, 0);
		gl.bindVertexArray(VAO_dice8);
		//循环渲染多个dice10 body
		for(let i = 0;i < body_dice8.length;i += 1){
			//获取运动状态
			body_dice8[i].getMotionState().getWorldTransform(TRANSFORM_AUX);
			
			let p = TRANSFORM_AUX.getOrigin();
			let q = TRANSFORM_AUX.getRotation();
			
			//用于局部坐标旋转的矩阵
			const rotate_cube = quad2matrix(q.x(), q.y(), q.z(), q.w());
			
			//uniform更新
			gl.uniform3f(programInfo_cube.uniformLocations.moveFloat, - move_x + p.x(), -move_y + p.y(), - move_z + p.z());//移动
			gl.uniformMatrix4fv(
				programInfo_cube.uniformLocations.partrotateMatrix,
				false,
				new Float32Array(rotate_cube),
			);
			
			gl.drawArrays(gl.TRIANGLES, 0, 3 * 8);
		}
		
		
		//dice4
		gl.uniform1i(programInfo_cube.uniformLocations.uSampler, 0);
		gl.bindVertexArray(VAO_dice4);
		//循环渲染多个dice10 body
		for(let i = 0;i < body_dice4.length;i += 1){
			//获取运动状态
			body_dice4[i].getMotionState().getWorldTransform(TRANSFORM_AUX);
			
			let p = TRANSFORM_AUX.getOrigin();
			let q = TRANSFORM_AUX.getRotation();
			
			//用于局部坐标旋转的矩阵
			const rotate_cube = quad2matrix(q.x(), q.y(), q.z(), q.w());
			
			//uniform更新
			gl.uniform3f(programInfo_cube.uniformLocations.moveFloat, - move_x + p.x(), -move_y + p.y(), - move_z + p.z());//移动
			gl.uniformMatrix4fv(
				programInfo_cube.uniformLocations.partrotateMatrix,
				false,
				new Float32Array(rotate_cube),
			);
			
			gl.drawArrays(gl.TRIANGLES, 0, 3 * 4);
		}
		

		//渲染边界
		gl.useProgram(programInfo_ground.program);
		gl.uniformMatrix4fv(
			programInfo_ground.uniformLocations.projectionMatrix,
			false,
			new Float32Array(perspec),
		);
		gl.uniformMatrix4fv(
			programInfo_ground.uniformLocations.rotateMatrix,
			false,
			new Float32Array(rotate),
		);

		gl.uniform3f(programInfo_ground.uniformLocations.moveFloat, - move_x, -move_y, - move_z);//移动
		
		gl.bindVertexArray(VAO_ground);
		gl.drawArrays(gl.TRIANGLES, 0, 6 * 5);
		


		requestAnimationFrame(render);
	}
	
	requestAnimationFrame(render);
}








main();
})

let angle_xz = 0;
let angle_y = -Math.PI / 2.0;
let x = 0;
let y = 0;
let isclick = false;

const move_speed = 0.1;
let move_x = 0;
let move_z = 0.0;
let move_y = 15.0;

let restart = 0;//指示是否重新开始
let magnetdown = 0;
//const screen_width = 640;
//const screen_height = 480;
//鼠标事件
function handle_mousemove(event){
	const x_current = event.offsetX;
	const y_current = event.offsetY;
	
	if(isclick){
		angle_xz +=  (x_current - x) / screen_width * Math.PI / 2.0;
		angle_y += (y_current - y) / screen_height * Math.PI / 2.0;
		//限位
		if(angle_y > Math.PI / 2.0){
			angle_y = Math.PI / 2.0;
		}else if(angle_y < -Math.PI / 2.0){
			angle_y = -Math.PI / 2.0;
		}
	}
	
	x = x_current;
	y = y_current;
}

function handle_mousedown(event){
	isclick = true;
}

function handle_mouseup(event){
	isclick = false;
}

function position_move(fr_ba, le_ri, angle){
	//前后运动
	move_z -= Math.cos(angle) * fr_ba;
	move_x -= Math.sin(angle) * fr_ba;
	
	//左右运动
	move_z -= -Math.sin(angle) * le_ri;
	move_x -= Math.cos(angle) * le_ri;
}


let w_down = 0;
let s_down = 0;
let a_down = 0;
let d_down = 0;
let q_down = 0;
let e_down = 0;
let f_down = 0;
function handle_keydown(event){
	switch(event.code){
		case "KeyW":
		w_down = 1;
		//position_move(move_speed, 0, angle_xz);
		
		break;
		case "KeyS":
		s_down = 1;
		//position_move(-move_speed, 0, angle_xz);
		break;
		case "KeyA":
		a_down = 1;
		//position_move(0, move_speed, angle_xz);
		break;
		case "KeyD":
		d_down = 1;
		//position_move(0, -move_speed, angle_xz);
		break;
		//增加上升和下降
		case "KeyQ":
		q_down = 1;
		//position_move(0, -move_speed, angle_xz);
		break;
		case "KeyE":
		e_down = 1;
		//position_move(0, -move_speed, angle_xz);
		break;
		case "KeyF":
		f_down = 1;
		//position_move(0, -move_speed, angle_xz);
		break;
	}
}

function handle_keyup(event){
	switch(event.code){
		case "KeyW":
		w_down = 0;
		
		break;
		case "KeyS":
		s_down = 0;
		break;
		case "KeyA":
		a_down = 0;
		break;
		case "KeyD":
		d_down = 0;
		break;
		//
		case "KeyQ":
		q_down = 0;
		break;
		case "KeyE":
		e_down = 0;
		break;
		case "KeyF":
		f_down = 0;
		break;
	}
}

//像素大小初始化
let screen_width = window.innerWidth;
document.querySelector("#glcanvas").width = screen_width;

let screen_height = window.innerHeight;
document.querySelector("#glcanvas").height = screen_height;

//事件监听
//document.addEventListener("DOMContentLoaded", main);
document.querySelector("#glcanvas").addEventListener("mousemove", handle_mousemove);
document.querySelector("#glcanvas").addEventListener("mousedown", handle_mousedown);
document.querySelector("#glcanvas").addEventListener("mouseup", handle_mouseup);
window.addEventListener("keydown", handle_keydown);
window.addEventListener("keyup", handle_keyup);

//骰子数量输入
let reset = 0;
const d4 = document.querySelector("#d4");
const d6 = document.querySelector("#d6");
const d8 = document.querySelector("#d8");
const d10 = document.querySelector("#d10");
const d12 = document.querySelector("#d12");
const d20 = document.querySelector("#d20");
document.querySelector("#reset").addEventListener("mousedown", (event) => {reset = 1});//控制按钮
document.querySelector("#cast").addEventListener("mousedown", (event) => {f_down = 1});//控制按钮